package verifycode

import (
	"fmt"
	"strings"
	"sync"
	"wskyygyso/api/pkg/app"
	"wskyygyso/api/pkg/config"
	"wskyygyso/api/pkg/helpers"
	"wskyygyso/api/pkg/logger"
	"wskyygyso/api/pkg/mail"
	"wskyygyso/api/pkg/redis"
	"wskyygyso/api/pkg/sms"
)

type VerifyCode struct {
	Store store
}

var once sync.Once

var internalVerifyCode *VerifyCode

func NewVerifyCode() *VerifyCode {
	once.Do(func() {
		internalVerifyCode = &VerifyCode{
			Store: &RedisStore{
				RedisClient: redis.Redis,
				// 增加前缀保持数据库整洁，出问题调试时也方便
				KeyPrefix: config.GetString("app.name") + ":verifycode:",
			},
		}
	})
	return internalVerifyCode
}

func (c *VerifyCode) generateVerifyCode(key string) string {
	code := helpers.RandomNumber(config.GetInt("verifycode.code_length"))
	//if app.IsLocal() {
	//	code = config.GetString("verifycode.debug_code")
	//}
	c.Store.Set(key, code)
	logger.DebugJson("验证码", "生成验证码", map[string]string{key: code})
	return code
}

func (c *VerifyCode) SendSms(phone string) bool {
	code := c.generateVerifyCode(phone)
	// 方便本地和 API 自动测试
	//if !app.IsProduction() && (strings.HasSuffix(phone, config.GetString("verifycode.debug_email_suffix")) ||
	//	strings.HasPrefix(phone, config.GetString("verifycode.debug_phone_prefix"))) {
	//	return true
	//}
	return sms.NewSms().Send(
		phone,
		sms.Message{
			Template: config.GetString("sms.aliyun.template_code"),
			Data:     map[string]string{"code": code},
		},
	)
}

func (c *VerifyCode) CheckAnswer(key string, val string) bool {
	return c.Store.Verify(key, val, false)
}

func (c *VerifyCode) SendMail(email string) error {
	code := c.generateVerifyCode(email)
	// 方便本地和 API 自动测试
	if !app.IsProduction() && strings.HasSuffix(email, config.GetString("verifycode.debug_email_suffix")) {
		return nil
	}
	content := fmt.Sprintf("<h1>你的email 验证码是 %v", code)
	//发送邮件
	mail.NewMailer().Send(mail.Email{
		From: mail.From{
			Address: config.GetString("mail.from.address"),
			Name:    config.GetString("mail.from.name"),
		},
		To:      []string{email},
		Subject: "email 验证码",
		HTML:    []byte(content),
	})
	return nil
}
